package org.oslims.server.service.impl;

import java.util.List;
import java.util.Set;
import java.util.UUID;

import net.sf.gilead.gwt.GwtConfigurationHelper;
import net.sf.gilead.gwt.PersistentRemoteService;

import org.hibernate.Session;
import org.oslims.client.service.UserService;
import org.oslims.domain.BaseUser;
import org.oslims.domain.Customer;
import org.oslims.domain.Department;
import org.oslims.domain.LabManager;
import org.oslims.domain.LabResponsible;
import org.oslims.domain.LabStaff;
import org.oslims.domain.Operator;
import org.oslims.server.dao.BaseDao;
import org.oslims.server.dao.CustomerDao;
import org.oslims.server.dao.LabManagerDao;
import org.oslims.server.dao.LabResponsibleDao;
import org.oslims.server.dao.OperatorDao;
import org.oslims.server.dao.hbm.HbmBaseUserDao;
import org.oslims.server.dao.hbm.HbmCustomerDao;
import org.oslims.server.dao.hbm.HbmDepartmentDao;
import org.oslims.server.dao.hbm.HbmLabManagerDao;
import org.oslims.server.dao.hbm.HbmLabResponsibleDao;
import org.oslims.server.dao.hbm.HbmLabStaffDao;
import org.oslims.server.dao.hbm.HbmOperatorDao;
import org.oslims.server.dao.util.HibernateUtil;

import com.google.gwt.validation.client.InvalidConstraint;
import com.google.gwt.validation.client.interfaces.IValidator;
import com.google.gwt.validation.server.ServerValidator;

public class UserServiceImpl extends PersistentRemoteService implements UserService {

	/**
	 * 
	 */
	private static final long serialVersionUID = -7484974323042503330L;
	Session session = HibernateUtil.getSession();
	BaseDao<BaseUser, Long> baseUserDao;
	BaseDao<LabStaff, Long> labStaffDao;
	OperatorDao operatorDao;
	LabManagerDao labManagerDao;
	LabResponsibleDao labResponsibleDao;
	CustomerDao customerDao;
	BaseDao<Department, Long> departmentDao;

	IValidator<Customer> customerValidatior = new ServerValidator<Customer>();
	IValidator<LabManager> labManagerValidatior = new ServerValidator<LabManager>();
	IValidator<LabResponsible> labResponsibleValidator = new ServerValidator<LabResponsible>();
	IValidator<Operator> operatorValidator = new ServerValidator<Operator>();

	public UserServiceImpl() {
		baseUserDao = new HbmBaseUserDao();
		departmentDao = new HbmDepartmentDao();
		labStaffDao = new HbmLabStaffDao();
		operatorDao = new HbmOperatorDao();
		labManagerDao = new HbmLabManagerDao();
		labResponsibleDao = new HbmLabResponsibleDao();
		customerDao = new HbmCustomerDao();

		net.sf.gilead.core.hibernate.HibernateUtil hibernateUtil = new net.sf.gilead.core.hibernate.HibernateUtil(HibernateUtil.getSessionFactory());
		setBeanManager(GwtConfigurationHelper.initGwtStatelessBeanManager(hibernateUtil));
	}

	@Override
	public List<Customer> getAllCustomer(int start, int length, String sortBy, boolean desc) {

		Session session = HibernateUtil.getSession();
		customerDao.setSession(session);

		List<Customer> response = customerDao.findAll(start, length, sortBy, desc);

		session.close();
		return response;
	}

	public void saveOrUpdateCustomer(Customer customer) {

		Set<InvalidConstraint<Customer>> violations = customerValidatior.validate(customer);

		if (violations.size() == 0) { // Only process the entity if valid!!!
			Session session = HibernateUtil.getSession();
			session.beginTransaction();
			try {
				customerDao.setSession(session);
				customerDao.makePersistent(customer);
				session.getTransaction().commit();
			} catch (RuntimeException e) {
				session.getTransaction().rollback();
				throw e;
			} finally {
				session.close();
			}
		}
	}

	@Override
	public List<LabManager> getAllLabManager(int start, int length, String sortBy, boolean desc) {

		Session session = HibernateUtil.getSession();
		labManagerDao.setSession(session);

		List<LabManager> response = labManagerDao.findAll(start, length, sortBy, desc);

		session.close();
		return response;
	}

	@Override
	public void saveOrUpdateLabManager(LabManager labManager) {

		if (labManagerValidatior.validate(labManager).size() == 0) {
			Session session = HibernateUtil.getSession();
			session.beginTransaction();
			try {
				labManagerDao.setSession(session);
				labManagerDao.makePersistent(labManager);
				session.getTransaction().commit();
			} catch (RuntimeException e) {
				session.getTransaction().rollback();
				throw e;
			} finally {
				session.close();
			}
		}
	}

	@Override
	public List<LabResponsible> getAllLabResponsible(int start, int length, String sortBy, boolean desc) {

		Session session = HibernateUtil.getSession();
		labResponsibleDao.setSession(session);

		List<LabResponsible> response = labResponsibleDao.findAllWithDepartments(start, length, sortBy, desc);

		session.flush();
		session.close();

		return response;
	}

	@Override
	public void saveOrUpdateLabResponsible(LabResponsible labResponsible) {

		if (labResponsibleValidator.validate(labResponsible).size() == 0) {
			Session session = HibernateUtil.getSession();
			session.beginTransaction();
			try {
				labResponsibleDao.setSession(session);
				labResponsibleDao.makePersistent(labResponsible);
				session.getTransaction().commit();
			} catch (RuntimeException e) {
				session.getTransaction().rollback();
				throw e;
			} finally {
				session.close();
			}
		}
	}

	@Override
	public List<Operator> getAllOperators(int start, int length, String sortBy, boolean desc) {

		Session session = HibernateUtil.getSession();
		operatorDao.setSession(session);

		List<Operator> response = operatorDao.findAllWithDepartments(start, length, sortBy, desc);

		session.close();
		return response;
	}

	@Override
	public void saveOrUpdateOperator(Operator operator) {

		System.out.println("Saving Operator: " + operator.getLastName() + " with " + operator.getDepartments().size() + " Departments");

		if (operatorValidator.validate(operator).size() == 0) {
			Session session = HibernateUtil.getSession();
			session.beginTransaction();
			try {
				operatorDao.setSession(session);
				operatorDao.makePersistent(operator);
				session.getTransaction().commit();
				System.out.println("Operator Saved!");
			} catch (RuntimeException e) {
				session.getTransaction().rollback();
				throw e;
			} finally {
				session.close();
			}
		}
	}

	@Override
	public BaseUser findByEMailAndPassword(String eMail, String password) {

		Session session = HibernateUtil.getSession();
		session.beginTransaction();

		baseUserDao.setSession(session);

		BaseUser bu = new BaseUser();

		bu.setEMail(eMail);
		bu.setPassword(password);

		BaseUser response = baseUserDao.findByExample(bu).get(0);

		response.setSessionId(UUID.randomUUID().toString());

		// baseUserDao.makePersistent(response);

		session.getTransaction().commit();
		session.close();
		return response;

	}

	@Override
	public Integer getCustomerCount() {
		Session session = HibernateUtil.getSession();
		customerDao.setSession(session);

		Integer response = customerDao.getEntityCount();

		session.close();
		return response;
	}

	@Override
	public Integer getLabManagerCount() {
		Session session = HibernateUtil.getSession();
		labManagerDao.setSession(session);

		Integer response = labManagerDao.getEntityCount();

		session.close();
		return response;
	}

	@Override
	public Integer getLabResponsibleCount() {
		Session session = HibernateUtil.getSession();
		labResponsibleDao.setSession(session);

		Integer response = labResponsibleDao.getEntityCount();

		session.close();
		return response;
	}

	@Override
	public Integer getOperatorCount() {
		Session session = HibernateUtil.getSession();
		operatorDao.setSession(session);

		Integer response = operatorDao.getEntityCount();

		session.close();
		return response;
	}

	@Override
	public List<Customer> getAllCustomer() {
		Session session = HibernateUtil.getSession();
		customerDao.setSession(session);

		List<Customer> response = customerDao.findAll();

		session.close();
		return response;
	}

	@Override
	public List<LabManager> getAllLabManager() {
		Session session = HibernateUtil.getSession();
		labManagerDao.setSession(session);

		List<LabManager> response = labManagerDao.findAll();

		session.close();
		return response;
	}

	@Override
	public List<LabResponsible> getAllLabResponsible() {
		Session session = HibernateUtil.getSession();
		labResponsibleDao.setSession(session);

		List<LabResponsible> response = labResponsibleDao.findAllWithDepartments();

		session.flush();
		session.close();

		return response;
	}

	@Override
	public List<Operator> getAllOperators() {
		Session session = HibernateUtil.getSession();
		operatorDao.setSession(session);

		List<Operator> response = operatorDao.findAllWithDepartments();

		session.close();
		return response;
	}
}
